/*

*/

#include "TeamOSFrame.h"

const u8 MANAGE_ENBALE=0x36; //任务管理使能值

/* 任务管理结构体体 */
struct
{
    type_TOSF_Task *task_tab;                                                                                //任务数组指针
    volatile u8 task_sum;                                                                                    //已注册任务数量
    u8 tab_max;                                                                                              //任务数组最大尺寸
    u8 enbale;                                                                                               //使能任务管理，避免先看中断时出错，使能=0x36(MANAGE_ENBALE)

/*优先级功能*/
#if USETOSF_TASK_PRIORITY
    u8 list_head;                                                                                            //链表头，存储最高优先级索引
    volatile u8 current_task;                                                                                //当前执行的任务,0xff=无任务 0-250=任务号
#endif
} _TaskManage;                                                                                               //创建任务管理体，用于任务调度

/* 系统时钟功能 */
#if USETOSF_SYSTIME_INFO
volatile u32 TOSF_SysTimeValue = 0;                                                                          //记录系统启动时间/ms，32bit：1193小时=49.7天
static volatile u16 _1ms_TaskTimer = 0;                                                                      //任务统计计时
#endif

/* 任务统计功能 */
#if USETOSF_INFO_FUNC
#include "stdio.h"
static volatile u16 _1ms_Printf = 0;
#endif

/*-------------------------------- Core ----------------------------------------*/

/**
 * 初始化全部变量
 * 初始化管理结构体，绑定任务数组
 * @param 1:任务数组，用以记录任务信息
 * @param 2:任务数组最大尺寸
 */
void TOSF_Init(type_TOSF_Task *task_tab, u8 tab_max)
{
    u8 i;

    _TaskManage.task_tab = task_tab;
    _TaskManage.tab_max = tab_max;
    _TaskManage.task_sum = 0;

    for (i = 0; i < _TaskManage.tab_max; i++)
    {
        _TaskManage.task_tab[i].state = 0;
        _TaskManage.task_tab[i].timer = 0;
        _TaskManage.task_tab[i].period = 0;
        _TaskManage.task_tab[i].func_p = (void *)0;
        _TaskManage.task_tab[i].period_bk = 0;

/* 优先级功能 */
#if USETOSF_TASK_PRIORITY
        task_tab->next_index = 0xff;                                                                         //链表索引指向空，0xff=空
#endif

/* 统计功能 */
#if USETOSF_INFO_FUNC
        _TaskManage.task_tab[i].run_total_time = 0;
        _TaskManage.task_tab[i].run_count = 0;
        _TaskManage.task_tab[i].task_name_p = 0;
#endif
    }
}

/**
 * 注册任务
 * @param ： 1-4
 * @return ：任务注册成功ID，0-250=任务ID，0xff=超过最大注册数量 0xfe=任务函数错误
 * @note :周期=0时轮询（此时需注意开启优先级后霸权问题）
 */
type_TaskId TOSF_LoginTask(void (*func_p)(void),                                                             //任务函数
                           u16 period,                                                                       //任务周期
                           u8 priority,                                                                      //任务优先级
                           char *name_p)                                                                     //任务打印时的名字
{
    type_TaskId result = 0xff;

    if (priority > 0x7f)
        priority = 0x7f;

    if (_TaskManage.task_sum >= _TaskManage.tab_max)
        result = 0xff;
    else if (func_p == (void *)0)
        result = 0xfe;
    else
    {
        result = _TaskManage.task_sum;
        _TaskManage.task_tab[_TaskManage.task_sum].state = priority;
        _TaskManage.task_tab[_TaskManage.task_sum].timer = 0;
        _TaskManage.task_tab[_TaskManage.task_sum].period = period;
        _TaskManage.task_tab[_TaskManage.task_sum].func_p = func_p;

/* 统计功能打开时才设置任务名，使用数组动态分配空间,内存溢出后名字乱码 */
#if USETOSF_INFO_FUNC
#include "string.h"
        static char name_buff[TASK_STRING_MAX];
        static u16 buff_index = 0;
        u16 temp;

        temp = strlen(name_p) + 1;
        if (temp > 200 - buff_index)
            buff_index = 0;
        _TaskManage.task_tab[_TaskManage.task_sum].task_name_p = &name_buff[buff_index];
        strcpy(_TaskManage.task_tab[_TaskManage.task_sum].task_name_p, name_p);
        buff_index += temp;
#endif

/* 优先级功能，链表方式 */
#if USETOSF_TASK_PRIORITY
        u8 i, last, now, next = 0;

        if (_TaskManage.task_sum == 0)
        {
            _TaskManage.list_head = 0;
            _TaskManage.task_tab[0].next_index = 0xff;                                                       //结束索引
        }
        else
        {
            now = _TaskManage.list_head;
            for (i = 0; i < _TaskManage.tab_max; i++)
            {
                /* 链表尾部直接插入，其他情况比对优先级，将高优先级任务插入链表前端 */
                if (now == 0xff)
                {
                    _TaskManage.task_tab[last].next_index = _TaskManage.task_sum;
                    _TaskManage.task_tab[_TaskManage.task_sum].next_index = 0xff;                            //链表尾部指向空
                    break;
                }
                else if (_TaskManage.task_tab[_TaskManage.task_sum].state > _TaskManage.task_tab[now].state) //刚注册的任务优先级高
                {
                    if (i == 0)                                                                              //链表开始位置采用额外变量存储
                    {
                        next = _TaskManage.list_head;
                        _TaskManage.list_head = _TaskManage.task_sum;
                        _TaskManage.task_tab[_TaskManage.task_sum].next_index = next;
                    }
                    else
                    {
                        _TaskManage.task_tab[last].next_index = _TaskManage.task_sum;
                        _TaskManage.task_tab[_TaskManage.task_sum].next_index = now;
                    }
                    break;
                }

                last = now;
                now = _TaskManage.task_tab[now].next_index;
            }
        }
#endif

        _TaskManage.task_sum++;

        _TaskManage.enbale = MANAGE_ENBALE; //注册任务后自动开启管理使能
    }

    return (result);
}

/* 优先级功能 */
#if USETOSF_TASK_PRIORITY
/**
 * 任务抢占
 * 抢占式任务调度，中断函数中调用，用于高优先级任务抢占
 * 默认在定时回调函数中使用，可单独添加在其他中断中实现嵌套
 * 注意：高优先级任务必须保证执行时间短
 */
void TOSF_TaskSeize(void)
{
    u8 i;
    u8 current = 0;
    u8 last_task;

    u8 next = _TaskManage.list_head;

    

    /* 遍历任务链表，寻找优先级在抢占级及以上的，若任务准备就绪，并且当前在执行低优先级任务则执行一次任务抢占执行
     * 优先级不满足则退出 */
    for (i = 0; i < _TaskManage.task_sum; i++)
    {
        current = next;
        next = _TaskManage.task_tab[next].next_index;

        if ((_TaskManage.task_tab[current].state) >= (TOSF_SEIZE_PRIORITY | 0x80))                           //优先级满足且处于运行态
        {
            /** 抢占任务优先级大于当前执行任务，空闲状态特殊判断 */
            if (_TaskManage.current_task == 0xff || 
                _TaskManage.task_tab[current].state > (_TaskManage.task_tab[_TaskManage.current_task%_TaskManage.task_sum].state | 0x80))
            {
                last_task = _TaskManage.current_task;
                _TaskManage.current_task = current;                                                          //记录当前，实现嵌套
                _TaskManage.task_tab[current].func_p();
                _TaskManage.task_tab[current].state &= 0x7f;

#if USETOSF_INFO_FUNC                                                                                        //使用统计信息时记录执行次数
                _TaskManage.task_tab[current].run_count++;
#endif
                _TaskManage.current_task = last_task;                                                        //恢复

                /* 任务执行时间要求必须短，所以不统计执行信息 */
                break;
            }
        }
        else                                                                                                 //优先级开始不满足则退出
            break;
    }
}
#endif

/**
 * 定时回调
 * 获取任务调度节拍
 * 任务运行态判断与切换
 * @param 1: 节拍ms数
 */
void TOSF_TimerCB(u8 _ms)
{
    u8 i;
    u16 t;

    if(_TaskManage.enbale != MANAGE_ENBALE) //未启用则退出
        return;

/* 任务统计功能 */
#if USETOSF_INFO_FUNC
    _1ms_Printf += _ms;
#endif

/* 系统时钟功能 */
#if USETOSF_SYSTIME_INFO
    _1ms_TaskTimer += _ms;
    TOSF_SysTimeValue += _ms;
#endif

    /* 轮询注册的任务，备用周期大于0时使用备用时间
     * 判断周期是否到后置位标志位
     * 时间为16bit */
    for (i = 0; i < _TaskManage.task_sum; i++)
    {
        _TaskManage.task_tab[i].timer += _ms;
        t = _TaskManage.task_tab[i].period;

        if (_TaskManage.task_tab[i].period_bk > 0)
            t = _TaskManage.task_tab[i].period_bk;

        if (_TaskManage.task_tab[i].timer >= t && (_TaskManage.task_tab[i].func_p != (void *)0))
        {
            _TaskManage.task_tab[i].timer = 0;
            _TaskManage.task_tab[i].state |= 0x80;
            _TaskManage.task_tab[i].period_bk = 0;
        }
    }

/* 优先级功能-任务抢占 */
#if USETOSF_TASK_PRIORITY
    TOSF_TaskSeize();
#endif
}

/**
 * 运行任务
 * 轮询，查询标志位后运行任务
 */
void TOSF_TaskHandler(void)
{
    u8 i;
    u8 idle_flag = 1;
    u8 current = 0;

/* 优先级功能 使用链表头 */
#if USETOSF_TASK_PRIORITY
    u8 next = _TaskManage.list_head;
#endif

    for (i = 0; i < _TaskManage.task_sum; i++)
    {

/* 优先级功能 找到链表中最大的优先级 */
#if USETOSF_TASK_PRIORITY
        current = next;
        next = _TaskManage.task_tab[next].next_index;
        if (current == 0xff)
            break;
#else
        current = i;
#endif

        if (_TaskManage.task_tab[current].state & 0x80)
        {

/* 优先级功能下，记录当前任务*/
#if USETOSF_TASK_PRIORITY
            _TaskManage.current_task = current;
#endif

/* 统计功能，统计任务执行时间 */
#if USETOSF_INFO_FUNC
            u32 info_t = TOSF_ExeTime(_TaskManage.task_tab[current].func_p);

            /* 存储最大执行时间 函数执行时间 累计总运行时间 函数执行次数统计 */
            if (_TaskManage.task_tab[current].run_max_time < (info_t))
                _TaskManage.task_tab[current].run_max_time = info_t;
            _TaskManage.task_tab[current].run_total_time += info_t;
            _TaskManage.task_tab[current].run_count++;
#else
            _TaskManage.task_tab[current].func_p();
#endif

            _TaskManage.task_tab[current].state &= 0x7f;

/* 优先级功能下 ，清空当前任务记录*/
#if USETOSF_TASK_PRIORITY
            _TaskManage.current_task = 0xff;
#endif

            idle_flag = 0;
            break;                                                                                           //一次只运行一个任务
        }
    }

    if (idle_flag == 1)                                                                                      //无任务运行时执行空闲任务
    {
        TOSF_IdleTask();
    }
}

/**
 * 指定时间任务运行一次
 * 延时一段时间运行（ms），=0时立刻运行
 * 运行完后自动恢复之前状态
 * 只运行一次，使用备份周期实现
 * @param 1:任务ID
 * @param 2:延时时间ms
 */
void TOSF_TaskRunOnce(type_TaskId id, u16 time)
{
    if (time == 0)
    {
        _TaskManage.task_tab[id].period_bk = 0;
        _TaskManage.task_tab[id].timer = 0;
        _TaskManage.task_tab[id].state |= 0x80;
    }
    else
    {
        _TaskManage.task_tab[id].period_bk = time;
        _TaskManage.task_tab[id].timer = 0;
        _TaskManage.task_tab[id].state &= 0x7f;
    }
}

/**
 * 设置任务周期
 */
void TOSF_SetTaskPeriod(type_TaskId id, u16 ms)
{
    _TaskManage.task_tab[id].period = ms;
}

#if USETOSF_SYSTIME_INFO

/**
 * 函数执行时间测量
 * 依赖TimeCB()中ms计时变量、us获取函数
 * 注意：函数不可重入，不能在中断中使用（依赖定时中断）
 * @param 1: 无参数无返回值函数指针
 * @param 2：执行时间，单位us
 */
u32 TOSF_ExeTime(void (*func)(void))
{
    u32 time_t;
    u32 current_us;

    /** 初始化时间起点 */
    _1ms_TaskTimer = 0;
    time_t = TOSF_GetSysTime_us();

    func();                                                                                                  //执行

    /* 先记录，防止极限情况下错误 */
    current_us = TOSF_GetSysTime_us();

    /** 若定时器溢出则加上溢出时间，否则只计算未溢出时间 */
    if (_1ms_TaskTimer > 0)
    {
        time_t = (current_us + 1000u) - time_t;
        time_t += (_1ms_TaskTimer - 1) * 1000u;
    }
    else
    {
        time_t = current_us - time_t;
    }

    return (time_t);
}

#endif

/*-------------------------------- Core End----------------------------------------*/

/* -----------------------------任务统计打印功能----------------------------- */
#if USETOSF_INFO_FUNC
/**
 * 任务信息打印函数
 * 说明：CPU占用及任务都开启,并且重定义了printf()才能输出
 */
void TOSF_TaskInfoPrint(void)
{
    u8 i;
    u32 t = 0;
    static u8 delay_flag = 0;

    /* 延时，间隔输出 */
    if (delay_flag > 0)
    {
        if (_1ms_Printf > 2000u || 1)
        {
            for (i = 0; i < _TaskManage.tab_max; i++)
            {
                _TaskManage.task_tab[i].run_total_time = 0;
                _TaskManage.task_tab[i].run_count = 0;
                _TaskManage.task_tab[i].run_max_time = 0;
            }
            delay_flag = 0;
            _1ms_Printf = 0;
        }
    }
    else if (_1ms_Printf > 1000u)
    {
        /* CPU占用率 */
        for (i = 0; i < _TaskManage.tab_max; i++)
        {
            t += _TaskManage.task_tab[i].run_total_time;                                                     //累计任务执行时间
        }

        printf("\r\n          CPU Used: %5.1f%%\r\n", t / 1.0e4);                                            //带小数百分数

        /* 单次运行时间 */
        printf("-----------------------------------\r\n");
        printf("TotalTime:  MaxTime:  RunCount:  TaskSN: \r\n\r\n");
        for (i = 0; i < _TaskManage.tab_max; i++)
        {
            if (_TaskManage.task_tab[i].run_total_time > 0 || _TaskManage.task_tab[i].run_count > 0)
            {
                printf("%6d us  %7d us  %3d       %s\r\n", _TaskManage.task_tab[i].run_total_time, _TaskManage.task_tab[i].run_max_time,
                       _TaskManage.task_tab[i].run_count, (char *)_TaskManage.task_tab[i].task_name_p);
                _TaskManage.task_tab[i].run_total_time = 0;
                _TaskManage.task_tab[i].run_count = 0;
                _TaskManage.task_tab[i].run_max_time = 0;
            }
        }
        printf("-----------------------------------\r\n\r\n");

        _1ms_Printf = 0;                                                                                     //复位重新统计
        delay_flag = 1;
    }
}
#endif

/*---------------------- 虚函数 ---------------------------------*/

/**
 * 空闲任务
 * 默认打印统计信息
 * 注意：需要满足运行时间低于1ms
 */
// __attribute__((weak)) void TOSF_IdleTask(void)
void TOSF_IdleTask(void)
{
/*CPU占用统计，默认间隔1S打印统计信息*/
#if USETOSF_INFO_FUNC
    TOSF_TaskInfoPrint();
#endif
}

// #include "tim.h"
/**
 * 获取当前系统us值
 * 需要外部重构，默认无功能，最大获取us值为999（%1000)
 * STM32F103 示例
 * @param 1:接收指针
 */
// __attribute__((weak)) u32 TOSF_GetSysTime_us(void)
u32 TOSF_GetSysTime_us(void)
{
    // return (htim1.Instance->CNT);
    return 0;
}

/*---------------------- 虚函数 End---------------------------------*/
